// @ts-ignore
import React from "react";
import ReactDOM from "react-dom";
import { Node } from "butterfly-dag";
import VMonacoEditor from "../components/MonacoEditor";
import $ from "jquery";

class BaseNode extends Node {
  [x: string]: any;
  endpointArray: any;
  opts: any;
  constructor(opts) {
    super(opts);
    this.opts = opts;
  }
  mounted() {
    if(this.endpointArray) {
      this.endpointArray.forEach(item => this.addEndpoint({
        id: item.id,
        dom: item.dom,
        ...item.opts
      }))
    }
  }
  draw = (data) => {
    const options = data.options;
    switch (options.type) {
      case "serial":
        return this._createSerialNode(options);
      case "keyboard":
      case "condition":
        return this._createKeyboardAndConditionNode(options, options.type);
      case "timer":
        return this.__createTimerNode(options);
      default:
        return this._createBaseNode(options);
    }
  }
  _createEndpointDot = (id, className, opts = {}) => {
    const endpoint = $(`<div class="endpoint-dot ${className}"></div>`);
    if (!this.endpointArray) this.endpointArray = [];
    this.endpointArray.push({
      dom: endpoint,
      id: this.opts.id ? `${this.opts.id}__$__${id}` : id,
      opts
    })
    return endpoint[0];
  }
  __createListDOM = (obj, prefix, opts) => {
    const listBody = $(`<ul class="node-${prefix}-list"></ul>`);
    Object.keys(obj).forEach(key => {
      let current = obj?.[key];
      const item = $(`<li class="${prefix}-item"><span class="label-text">${current.name}</span></li>`);
      item.append(this._createEndpointDot(key, `${prefix}-endpoint`, opts));
      listBody.append(item);
    });
    return listBody;
  }
  __createBaseContainer = (opts, prefix?) => {
    const container = $(`<div class="visbar-blueprint-node ${ prefix ? `${prefix}-node` : "" }"></div>`)
    .css("top", opts.top)
    .css("left", opts.left)
    .attr("id", opts.id);
    let nodeHeader = $(`<div class="node-header"><span>${opts.title}</span></div>`);
    container.append(nodeHeader);
    return container;
  }
  _createBaseNode = (opts) => {
    let container = this.__createBaseContainer(opts);
    if (opts.event) {
      let eventBody = $(`<div class="node-event-wrapper"><p>事件</p></div>`);
      eventBody.append(this.__createListDOM(opts.event, "event", { type: "source" }));
      container.append(eventBody);
    }
    if (opts.action) {
      let actionBody = $(`<div class="node-action-wrapper"><p>动作</p></div>`);
      actionBody.append(this.__createListDOM(opts.action, "action", { type: "target" }));
      container.append(actionBody);
    }
    return container[0];
  }
  _createSerialNode = (opts) => {
    let container = this.__createBaseContainer(opts, "serial");
    const nodeBody = $(`<div class="serial-node-body"><button class="serial-node-btn">处理函数</button></div>`);
    nodeBody.append(this._createEndpointDot("serial-enter", "serial-enter-dot", { type: "target" }));
    nodeBody.append(this._createEndpointDot("serial-output", "serial-output-dot", { type: "source" }));
    nodeBody.find(".serial-node-btn").on("click", () => {
      this.__openMonacoEditor({
        onChange: (value) => {
          this.cacheCode = value;
          this.emit("node.change", { options: opts, value });
        },
        value: this.cacheCode || opts?.funcBody
      });
    })
    container.append(nodeBody);
    return container[0];
  }
  _createKeyboardAndConditionNode = (opts, key) => {
    let container = this.__createBaseContainer(opts, key);
    const nodeBody = $(`<div class="${key}-node-body"></div>`);
    opts.action && nodeBody.append(this.__createListDOM(opts.action, "action", { type: "target" }));
    opts.event && nodeBody.append(this.__createListDOM(opts.event, "event", { type: "source" }));
    container.append(nodeBody);
    return container[0];
  }
  __createTimerNode = (opts) => {
    let container = this.__createBaseContainer(opts, "timer");
    const numberInput = $(`<div class="timer-delay-container"><input type="number" value="${opts.delay}" class="delay-input" min="0" /></div>`);
    container.append(numberInput);
    numberInput.find(".delay-input").on("change", (ev) => {
      const value = Number((ev.target as any).value) || 0;
      this.emit("node.change", { options: opts, value });
    })
    const nodeBody = $(`<div class="timer-node-body"></div>`);
    opts.action && nodeBody.append(this.__createListDOM(opts.action, "action", { type: "target" }));
    opts.event && nodeBody.append(this.__createListDOM(opts.event, "event", { type: "source" }));
    container.append(nodeBody);
    return container[0];
  }
  __openMonacoEditor = (options) => {
    this.monacoContainer = document.getElementById("visbar-blueprint-monaco-wrapper");
    if (!this.monacoContainer) {
      this.monacoContainer = document.createElement("div");
      this.monacoContainer.id = "visbar-blueprint-monaco-wrapper";
      document.body.appendChild(this.monacoContainer);
    }
    ReactDOM.render(<VMonacoEditor {...options} onClose={this.__closeMonacoEditor} />, this.monacoContainer)
  }
  __closeMonacoEditor = () => {
    this.monacoContainer && ReactDOM.unmountComponentAtNode(this.monacoContainer);
  }
}

export default BaseNode;